package com.smartlink.task;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.json.JSONArray;
import org.json.JSONObject;

import com.smartlink.pojo.Classroom;
import com.smartlink.pojo.Sensors;
import com.smartlink.pojo.Setting;
import com.smartlink.util.Common;
import com.smartlink.util.HttpClientUtil;
import com.smartlink.util.JpushUtil;

public class Task {
	private SessionFactory sessionFactory;
	private JpushUtil jpushUtil;
	private HttpClientUtil clientUtil;
	private Map<String, Integer> count = new LinkedHashMap<>();
	private List<String> cameras = new ArrayList<>();
	private static Log log = LogFactory.getLog(Task.class);

	public Task() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Task(SessionFactory sessionFactory, JpushUtil jpushUtil, HttpClientUtil clientUtil) {
		super();
		this.sessionFactory = sessionFactory;
		this.jpushUtil = jpushUtil;
		this.clientUtil = clientUtil;
	}

	public JpushUtil getJpushUtil() {
		return jpushUtil;
	}

	public void setJpushUtil(JpushUtil jpushUtil) {
		this.jpushUtil = jpushUtil;
	}

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public HttpClientUtil getClientUtil() {
		return clientUtil;
	}

	public void setClientUtil(HttpClientUtil clientUtil) {
		this.clientUtil = clientUtil;
	}

	public Session getSession() {
		return this.sessionFactory.openSession();
	}

	public void closeSession(Session session) {
		session.close();
	}

	public List<Classroom> getClassroomList() {
		String hql = "FROM Classroom";
		Session session = getSession();
		Transaction tr = session.beginTransaction();
		@SuppressWarnings("unchecked")
		List<Classroom> list = session.createQuery(hql).list();
		tr.commit();
		closeSession(session);
		return list;

	}

	public void envMethod() {
		List<Classroom> list = getClassroomList();
		if (list.isEmpty()) {
			log.warn("没有教室");
			return;
		}
		for (Classroom classroom : list) {
			// 获取ip
			String ip = classroom.getPiIp();
			// 获取环境传感器
			List<Sensors> sensorList = getEnvSensors(classroom.getSensorses());
			// 判断是否存在传感器，如果没有则结束
			if (sensorList.isEmpty()) {
				log.warn("没有传感器");
				return;
			}
			// 获取传感器接口
			String sensorUri = sensorList.get(0).getApi();
			String piUrl = "http://" + ip + sensorUri;
			// 获取树莓派数据
			JSONObject getData = clientUtil.doGet(piUrl);
			if (getData == null) {
				log.warn("连接失败");
				return;
			}
			// 解析数据 做出相应改变
			// 计算土壤相对湿度
			String soilRh = (String) getData.remove("soilRh");
			DecimalFormat df=new DecimalFormat("##0.00");
			double rh = 100 - (Double.parseDouble(soilRh) - 91) * 0.609;
			if (rh > 100) {
				rh = 95.5;
			} else if (rh < 1) {
				rh = 20;
			}
			getData.put("soilRh", df.format(rh));
			// 判断数据 推送
			jpush(getData, classroom.getSetting());
			// 上传数据
			log.info("上传环境数据");
			String uploadUrl = "http://api.heclouds.com/devices/" + classroom.getDeviceId() + "/datapoints?type=3";
			clientUtil.doPost(uploadUrl, getData);

		}

	}

	/**
	 * 判断数据值，做出相应推送
	 * 
	 * @param json
	 */
	public void jpush(JSONObject json, Setting setting) {
		StringBuilder sb = new StringBuilder();
		double soilRh = json.getDouble("soilRh");
		double roomTemperature = Double.parseDouble(json.getString("roomTemperature"));
		if (soilRh < setting.getSoilRh() - 8) {
			sb.append("盆栽需要浇水。\n");
		}
		if (roomTemperature > setting.getRoomTemperature() + 5) {
			sb.append("温度过高,是否开启空调进行制冷?\n");
		} else if (roomTemperature < setting.getRoomTemperature() - 5) {
			sb.append("温度过低,是否开启空调进行加热?\n");
		}
		JpushUtil.sendJpush(sb.toString());
	}

	public void safeMethod() {
		List<Classroom> list = getClassroomList();
		if (list.isEmpty()) {
			log.warn("没有教室");
			return;
		}
		for (Classroom classroom : list) {
			// 获取ip
			String ip = classroom.getPiIp();
			// 获取安全传感器
			List<Sensors> sensorList = getSafeSensors(classroom.getSensorses());
			if (sensorList.isEmpty()) {
				log.warn("没有传感器");
				return;
			}
			log.info("count:" + count);
			// 获取传感器接口
			String sensorUri = sensorList.get(0).getApi();
			String piUrl = "http://" + ip + sensorUri;
			String cameraUrl = "http://" + ip + ":8080/smartpi/CameraServlet?device_id=" + classroom.getDeviceId();
			// 获取Setting
			Setting setting = classroom.getSetting();
			// 判断setting设置 如果为1表示开启警报
			if (setting.getIsAlarm() == 1) {
				// 获取树莓派数据
				JSONObject getData = clientUtil.doGet(piUrl);
				if (getData == null) {
					log.warn("连接失败");
					return;
				}
				// 判断当前时间是否在报警时间内
				if (isInAlearmTime(setting)) {
					log.info("安全检查开始");
					checkSafe(setting, getData, cameraUrl);
				}
				log.info("上传安全数据");
				// 上传数据
				String uploadUrl = "http://api.heclouds.com/devices/" + classroom.getDeviceId() + "/datapoints?type=3";
				clientUtil.doPost(uploadUrl, getData);

			} else {
				log.info("不进行安全检查");
			}

		}

	}

	/**
	 * 检查安全信息
	 */
	public void checkSafe(Setting setting, JSONObject data, String cameraUrl) {
		String window = data.getString("window");
		String smoke = data.getString("smoke");
		String fire = data.getString("fire");
		String people = data.getString("people");
		// 根据设置判断安全性
		// 检测门窗是否开启
		boolean windowFlag = isWindowOpen(window);
		boolean peopleFlag = isPeople(people, cameraUrl);
		boolean smokeFlag = isSmoke(smoke);
		boolean fireFlag = isFire(fire);
		// 确定异常
		String pwCode = "000";
		String sfCode = "000";
		if (windowFlag && peopleFlag) {
			pwCode = Common.PEOPLE_WINDOW;
		} else if (windowFlag && !peopleFlag) {
			pwCode = Common.WINDOW;
		} else if (!windowFlag && peopleFlag) {
			pwCode = Common.PEOPLE;
		}

		if (smokeFlag && fireFlag) {
			sfCode = Common.FIRE_SMOKE;
		} else if (smokeFlag && !fireFlag) {
			sfCode = Common.SMOKE;
		} else if (!smokeFlag && fireFlag) {
			sfCode = Common.FIRE;
		}
		// 修改照片索引
		JSONArray array = new JSONArray(cameras);
		setting.setCamera(array.toString());

		// 修改错误代码 错误代码不相等时修改
		String error = pwCode + sfCode;
		// 是否响铃
		if (!error.equals("000000")) {
			ring(setting, cameraUrl);
		}
		if (setting.getErrorCode() == null || !setting.getErrorCode().equals(error)) {
			setting.setErrorCode(error);
			Session session = getSession();
			Transaction tr = session.beginTransaction();
			session.update(setting);
			tr.commit();
			closeSession(session);
			log.info("修改ErrorCode" + error);
		}

	}

	/**
	 * 响铃
	 * 
	 * @param setting
	 * @param url
	 */
	public void ring(Setting setting, String cameraUrl) {
		String[] urls = cameraUrl.split("\\?");
		int index = urls[0].indexOf("CameraServlet");
		String rootUrl = urls[0].substring(0, index);
		if (setting.getIsAiRegulate() == 1) {
			// 响铃
			clientUtil.doGet(rootUrl + "RingServlet");
		} else {
			;
		}
	}

	/**
	 * 检测当前时间是否在报警时间内
	 * 
	 * @param setting
	 * @return
	 */
	public boolean isInAlearmTime(Setting setting) {
		java.util.Calendar localTime = java.util.Calendar.getInstance();
		java.util.Calendar beginTime = java.util.Calendar.getInstance();
		java.util.Calendar overTime = java.util.Calendar.getInstance();
		beginTime.setTime(setting.getAlarmBeginDate());
		overTime.setTime(setting.getAlarmOverDate());
		localTime.set(Calendar.YEAR, beginTime.get(Calendar.YEAR));
		localTime.set(Calendar.MONTH, beginTime.get(Calendar.MONTH));
		localTime.set(Calendar.DAY_OF_MONTH, beginTime.get(Calendar.DAY_OF_MONTH));

		int resultBegin = localTime.compareTo(beginTime);
		int resultOver = localTime.compareTo(overTime);
		if (0 < resultBegin && resultOver < 0) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 根据教室id获取设置
	 * 
	 * @param clsroom
	 * @return
	 */
	public Setting getSetting(Classroom clsroom) {
		Session session = getSession();
		Transaction tr = session.beginTransaction();
		String hql = "FROM Setting WHERE id=?";
		Setting setting = (Setting) session.createQuery(hql).setInteger(0, clsroom.getId()).uniqueResult();
		tr.commit();
		closeSession(session);
		return setting;
	}

	/**
	 * 得到所有环境数据
	 * 
	 * @param set
	 * @return
	 */
	private List<Sensors> getEnvSensors(Set<Sensors> set) {
		List<Sensors> sensorList = new ArrayList<Sensors>();
		for (Sensors s : set) {
			if (s.getType() == 1) {
				sensorList.add(s);
			}
		}
		return sensorList;
	}

	/**
	 * 得到安全传感器
	 * 
	 * @param set
	 * @return
	 */
	private List<Sensors> getSafeSensors(Set<Sensors> set) {
		List<Sensors> sensorList = new ArrayList<Sensors>();
		for (Sensors s : set) {
			// 排除照相机
			if (s.getType() == 0 && !"".equals(s.getApi().trim())) {
				sensorList.add(s);
			}
		}
		return sensorList;
	}

	/**
	 * 检测窗户是否打开
	 * 
	 * @param setting
	 * @param one
	 * @param two
	 * @return
	 */
	private boolean isWindowOpen(String window) {
		if ("1".equals(window)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 是否有人
	 * 
	 * @param people
	 * @param cameraUrl
	 *            拍照url
	 * @return
	 */
	private boolean isPeople(String people, String cameraUrl) {
		int value = 0;
		String key = "people";
		if ("1".equals(people)) {
			// new Thread(new CameraRunnable(clientUtil, cameraUrl)).start();
			// 拍照
			JSONObject getData = null;
			do {
				log.info("拍照");
				getData = clientUtil.doGet(cameraUrl);
			} while (getData == null);

			String camera = (String) getData.getJSONObject("data").get("index");
			cameras.add(camera);

			// 分析误差
			value = incCount(key);
		} else {
			count.remove(key);
			cameras.clear();
		}

		if (value > 3) {
			return true;
		} else {
			return false;
		}

	}

	/**
	 * 是否有火焰
	 * 
	 * @param fire
	 * @return
	 */
	private boolean isFire(String fire) {
		if ("1".equals(fire)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 是否有烟雾
	 * 
	 * @param smoke
	 * @return
	 */
	private boolean isSmoke(String smoke) {
		if ("1".equals(smoke)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 统计函数 自加1
	 * 
	 * @param key
	 * @return
	 */
	private int incCount(String key) {
		if (!count.containsKey(key)) {
			count.put(key, 0);
		}
		int value = count.get(key);
		++value;
		count.put(key, value);
		return value;

	}

	/*
	 * class CameraRunnable implements Runnable { private HttpClientUtil client;
	 * private String cameraUrl;
	 * 
	 * public CameraRunnable(HttpClientUtil client, String cameraUrl) { super();
	 * this.client = client; this.cameraUrl = cameraUrl; }
	 * 
	 * @Override public void run() { // TODO Auto-generated method stub
	 * client.doGet(cameraUrl);
	 * 
	 * }
	 * 
	 * }
	 */

}
